import { Location } from '@angular/common';
import { ChangeDetectorRef, Component, Input, OnInit, Output, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AfMessageService } from '@core';
import { STColumn, STComponent } from '@delon/abc/st';
import { _HttpClient } from '@delon/theme';
import { copy } from '@delon/util';
import { NzModalService } from 'ng-zorro-antd/modal';
import { BehaviorSubject, Observable, of, zip } from 'rxjs';
import { catchError, debounceTime, map, switchMap } from 'rxjs/operators';

import { CodeGenService } from '../../codegen.service';
import { ActionType, ConstNamingRule, LangScriptType, LangSourceType } from '../lang';
import { LangService } from '../lang.service';

@Component({
  selector: 'app-cg-lang-db-script',
  templateUrl: './lang-db-script.component.html',
  styleUrls: ['./lang-db-script.component.less']
})
export class LangDBScriptComponent implements OnInit {
  namingRuleList = ConstNamingRule;

  sourceType: any = LangSourceType.database;
  actionType: any = ActionType.edit;
  sourceLabel: any = undefined;
  sourceTable: any = undefined;
  // 数据库名称或父节点名称
  sourceName: any = undefined;
  scriptDbType: any = 'mysql';

  targetDataBases: any[] | null = null;
  targetDataBase: any = undefined;

  autoFormat: any = true;
  colPrefix: any = '';
  colSuffix: any = '';
  tableAlias: any = '';

  isLoading = false;
  namingRule = 'same';
  record: any;

  codeMirrorOptions = {
    lineNumbers: true,
    theme: 'dracula',
    mode: 'sql',
    readOnly: true
  };

  copyCode() {
    copy(this.tmpScript);
    this.msg.msg_success('复制成功');
  }

  constructor(
    private router: Router,
    private modal: NzModalService,
    private location: Location,
    private route: ActivatedRoute,
    private msg: AfMessageService,
    private codegen: CodeGenService,
    private cdr: ChangeDetectorRef,
    private langServ: LangService
  ) {}

  ngOnInit(): void {
    const param = this.route.snapshot.queryParams;
    if (param && param['sourceType']) {
      this.initParamData(param);
      console.log(`param${JSON.stringify(param)}`);
    }
    if (this.record) {
      this.initParamData(this.record);
      console.log(`record${this.record}`);
    }

    this.queryDatabaseType();
    this.queryDataSource();
  }

  initParamData(param: any) {
    this.actionType = param['actionType'];
    this.sourceType = param['sourceType'];
    this.sourceName = param['sourceName'];
    this.sourceTable = param['sourceTable'];
    this.namingRule = param['namingRule'];
    this.scriptDbType = param['scriptDbType'];
    this.sourceLabel = param['sourceLabel'];
  }

  databaseTypes: any[] = [];
  public queryDatabaseType() {
    this.isLoading = true;
    this.cdr.detectChanges();
    try {
      this.codegen.getDataTypeList().subscribe(body => {
        if (body.status) {
          this.databaseTypes = [];
          this.databaseTypes = body.data;
        } else {
          this.msg.notice_warning('查询数据库类型列表', `警告编号${body.code};  警告信息${body.msg}`);
        }
      });
    } finally {
      setTimeout(() => {
        this.isLoading = false;
        this.cdr.detectChanges();
      }, 200);
    }
  }

  dbSourceOptions: any[] = [];
  dbCurrentOptions: any[] = [];
  public queryDataSource() {
    this.isLoading = true;
    this.cdr.detectChanges();
    this.langServ.queryDbSourceCascader().subscribe(body => {
      if (body.status) {
        this.dbSourceOptions = body.data;
        this.dbCurrentOptions = this.dbSourceOptions;
        // console.log(this.dbSourceOptions);
      } else {
        this.msg.notice_warning('查询数据源', `警告编号${body.code};  警告信息${body.msg}`);
      }
    });
  }
  // 获取目标数据源
  onCascaderTargetChanges(values: any): void {
    if (values != undefined && values != null) {
      this.targetDataBase = values![1];
    }
    this.forcedExecute = false;
  }

  public checkParam(): boolean {
    if (this.codegen.isEmpty(this.sourceName)) {
      this.msg.notice_warning('警告信息', `请选择数据源`);
      return false;
    }
    if (this.codegen.isEmpty(this.sourceTable)) {
      this.msg.notice_warning('警告信息', `请输入并选择表`);
      return false;
    }
    return true;
  }

  ddlScripts = '';
  columnScripts = '';
  dqlScripts = '';
  dmlScripts = '';
  public getTableAllScript(): void {
    if (this.scriptDbType == 'flink' && this.targetDataBase === undefined) {
      this.msg.notice_warning('警告信息', `请选择Flink连接器`);
      return;
    }

    this.ddlScripts = '';
    this.dqlScripts = '';
    this.dmlScripts = '';
    this.columnScripts = '';
    this.isLoading = true;
    this.langServ
      .getTableAllScript(
        this.sourceType,
        this.sourceName,
        this.sourceTable,
        this.namingRule,
        this.scriptDbType,
        this.targetDataBase,
        this.colPrefix,
        this.colSuffix,
        this.tableAlias
      )
      .subscribe(body => {
        if (body.status) {
          const scripts: any[] = body.data;
          console.log(scripts);
          scripts.forEach(item => {
            let formatScript = item.script;
            if (this.autoFormat) {
              formatScript = this.codegen.sqlformat(item.script, this.scriptDbType);
            }
            if (
              item.scriptType == LangScriptType.drop ||
              item.scriptType == LangScriptType.create ||
              item.scriptType == LangScriptType.index ||
              item.scriptType == LangScriptType.comment
            ) {
              this.ddlScripts = `${this.ddlScripts + formatScript};\n`;
            } else if (
              item.scriptType == LangScriptType.insert ||
              item.scriptType == LangScriptType.update ||
              item.scriptType == LangScriptType.delete
            ) {
              this.dmlScripts = `${this.dmlScripts + formatScript};\n`;
            } else if (item.scriptType == LangScriptType.columns) {
              this.columnScripts = `${this.columnScripts + formatScript};\n`;
            } else if (item.scriptType == LangScriptType.select) {
              this.dqlScripts = `${this.dqlScripts + formatScript};\n`;
            }
          });
        } else {
          this.msg.notice_warning('脚本生产失败', `警告信息: ${body.msg} ; ${body.data}`);
        }
        this.isLoading = false;
        this.scriptTabChanged();
        this.cdr.detectChanges();
      });
  }

  forcedExecute: boolean = false;
  executeScriptClick() {
    if (!this.targetDataBase) {
      this.msg.msg_warning(`请选择目标数据库`);
      return;
    }
    if (this.scriptDbType == 'flink') {
      this.msg.msg_warning(`${this.scriptDbType}数据库不支持执行脚本`);
      return;
    }

    this.modal.create({
      nzTitle: '执行脚本',
      nzContent: '是否将表创建到目标数据库？',
      nzClosable: false,
      nzOnOk: () => this.executeScript(this.forcedExecute)
    });
  }

  executeScript(forced: boolean = false) {
    try {
      this.ddlScripts = '';
      this.dqlScripts = '';
      this.dmlScripts = '';
      this.columnScripts = '';
      this.isLoading = true;
      this.langServ
        .executeDllScript(
          this.sourceType,
          this.sourceName,
          this.sourceTable,
          this.namingRule,
          this.scriptDbType,
          this.targetDataBase,
          forced
        )
        .subscribe(body => {
          if (body.status) {
            const scripts: any[] = body.data;
            this.msg.msg_success('执行脚本成功');
          } else {
            this.msg.msg_error(`执行脚本失败: ${body.msg}`);
          }
        });
    } finally {
      setTimeout(() => {
        this.isLoading = false;
        this.cdr.detectChanges();
      }, 300);
    }
  }

  selectedTabIndex = 0;
  tableLoading = false;

  backPage() {
    this.location.back();
  }

  getSourceType() {
    if (this.sourceType == LangSourceType.database) {
      return `数据库/${this.sourceName}`;
    } else {
      return `元数据/${this.sourceName}`;
    }
  }

  openScriptLog(record: any = {}) {
    this.router.navigateByUrl(`/codegen/database/script/log?sourceId=${this.sourceTable}`);
  }

  tmpScript: any;
  scriptTabChanged() {
    // console.log(value);
    if (this.selectedTabIndex == 0) {
      this.tmpScript = this.ddlScripts;
    }
    if (this.selectedTabIndex == 1) {
      this.tmpScript = this.dmlScripts;
    }
    if (this.selectedTabIndex == 2) {
      this.tmpScript = this.columnScripts;
    }
    if (this.selectedTabIndex == 3) {
      this.tmpScript = this.dqlScripts;
    }
    // console.log(this.tmpScript);
    this.cdr.detectChanges();
  }
}
